iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 20
0
自我挑戰組

前端工程師的30份套餐系列 第 20

Day20-閉包(二)

  • 分享至 

  • xImage
  •  

首先來看一個例子:

function func() {
    var arr = [];
    for(var i=0; i<3; i++) {
        arr.push(
            function() {
                console.log(i);
            }
        )
    }
    return arr;
}

var funcResult = func();

funcResult[0]();
funcResult[1]();
funcResult[2]();

1.在function 宣告空陣列
2.再寫一個for迴圈,變數i是計數器,只要小於3,就會繼續執行
3.記得Day10提到的push()嗎?這時候就透過這方法,在迴圈內的陣列中增加東西
4.接著再新增一個函式,把i輸出
5.用函式表達式新增三個新的函式物件給陣列
6.for迴圈結束後,會有三個一模一樣的函式在陣列裡
7.然後這些函式會回傳該陣列
8.接下來,呼叫func函式來得到陣列
9.console.log(funcResult)的話會看到三個陣列
10.記得這些函式在陣列中
11.是可以參考到的,像執行第一個就是funcResult0
12.接著將三個函式執行
13.最後,這三個函式分別會印出什麼?
會是0,1,2嗎?
.
.
.
.
.
.
.
.
.
.
答案是會印出3,3,3(如果用ES6的let宣告的話會印出0,1,2)
原是是什麼?
因為,func函式跑完for迴圈,i的值是3,並且return的arr,陣列arr有三個函式。
然而在最後執行了陣列中的三個函式,但是console.log(i),在執行時裡面並沒有變數i,所以到外部去找,找到func函式內,i的結果值是3,所以就console.log(3),所以三個函式也一樣都是3,他們都指向同一個記憶體位置,因為他們被建立在同一個函式func內。

還是不太懂嗎? 這裡我也研究了滿久
因為當執行函式時,只會告訴你現在記憶體中的值是什麼,而不是創造函式時候的值,只有在真的執行函式時他們三個輸出都是一樣。
console.log不是在它所在的地方執行,而是在呼叫函式的時後才執行的


那現在換一個方式改寫上面那段範例
在arr.push方法裡改成立即執行函式,每次迴圈執行時,j都會被存在這三個執行環境,幸虧有閉包,所以印出來的結果就會是0,1,2,

function func2() {
    var arr = [];
    for(var i=0; i<3; i++) {
        arr.push(
            (function(j){
                return function(){
                    console.log(j)
                }
            })(i)
        )
    }
    return arr;
}

var funcResult2 = func2();

funcResult2[0]();
funcResult2[1]();
funcResult2[2]();

上一篇
Day19- 閉包(一)
下一篇
Day21-Curry(柯里化)
系列文
前端工程師的30份套餐30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言